package edu.tcc.iot.controler.impl;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.sql.SQLException;

import org.apache.log4j.Logger;

import edu.tcc.iot.core.services.IMailerService;
import edu.tcc.iot.core.services.IShelfService;
import edu.tcc.iot.core.services.impl.MailerService;
import edu.tcc.iot.domain.Product;
import edu.tcc.iot.domain.Shelf;
import edu.tcc.iot.domain.vo.ProductVO;
import edu.tcc.iot.domain.vo.ShelfVO;
import edu.tcc.iot.utils.Parser;
import edu.tcc.iot.utils.ServiceLocator;

public class ShelfThread implements Runnable {

	private final static Logger log = Logger.getLogger(ShelfThread.class);
	private IShelfService shelfService = ServiceLocator.getInstance(IShelfService.class); 
	private IMailerService mailerService = MailerService.getInstance();

	private Socket socket;
	private ObjectInputStream objectInputStrem;
	private long shelfId; 

	public ShelfThread(Socket socket) {
		try {
			log.info("[CERS][ShelfThread] - Constructor of new ShelfThread started");
			this.socket = socket;
			objectInputStrem = new ObjectInputStream(socket.getInputStream());
			Shelf shelf = readShelf();
			shelfId = shelf.getId();
			shelfId = shelfService.saveShelf(shelf).id;
			log.info("[CERS][ShelfThread] - New ShelfThread Initiate ShelfID = " + shelfId);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}

	private Shelf readShelf(){
		log.info("[CERS][ShelfThread] - Reading Shelf Info");
		try {
			if(!socket.isConnected()){
				return null;
			}
			ShelfVO vo = (ShelfVO) objectInputStrem.readObject();
			log.info("[CERS][ShelfThread] - New Shelf Readed");
			return Parser.fromShelfVO(vo);
		} catch (ClassNotFoundException e) {
			log.error("[CERS][ShelfThread] - Wrong Shelf Cast");
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		log.info("[CERS][ShelfThread] - No Shelf Founded");
		return null;
	}

	@Override
	public void run() {
		try{
			Shelf shelf = shelfService.findById(shelfId);
			log.info("[CERS][ShelfThread] - ShelfThread Started");

			while(socket.isConnected()){
				try {
					Product product = readProduct();
					log.info("[CERS][ShelfThread] - Product received "+ product.toString());
					if(!shelf.isProductEqual(product)){
						shelfService.addProductToShelf(product, shelf.id);
					}
					if(!shelf.existProduct(product)){
						shelf.addProduct(product);
					}
					validateProduct(product);
					Thread.sleep(6000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			shelfService.saveShelf(shelf);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	private Product readProduct() {
		try {
			if(!socket.isConnected()){
				return null;
			}
			ProductVO vo = (ProductVO) objectInputStrem.readObject();
			return Parser.fromProductVO(vo);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	private void validateProduct(Product product) {
		if(!product.hasWarningSent()){
			if(product.isLevelLow()){
				mailerService.sendProductLevelWarningEmail(product);
			}
			if(product.isValidate()){
				mailerService.sendProductValidateWarningEmail(product);
			}
		}
	}

}
